package cz.muni.fi.pa165.dundd.soap.client;

import static cz.muni.fi.pa165.dundd.soap.client.Client.serverAvailable;
import cz.muni.fi.pa165.dundd.soap.server.AdministratorDTO;
import cz.muni.fi.pa165.dundd.soap.server.AdministratorSOAP;
import cz.muni.fi.pa165.dundd.soap.server.AdministratorSOAP_Service;
import cz.muni.fi.pa165.dundd.soap.server.TroopDTO;
import cz.muni.fi.pa165.dundd.soap.server.TroopSOAP;
import cz.muni.fi.pa165.dundd.soap.server.TroopSOAP_Service;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Scanner;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.SOAPFaultException;

public class Client {

    private static AdministratorSOAP administratorSoap;
    private static TroopSOAP troopSoap;

    public static void main(String[] args) {
        //check server availability
        if (!isServerOnline()) {
            return;
        }
        System.out.println("\n\n\n Now the client is running. \n\n");

        String input = null;
        troopSoap = new TroopSOAP_Service().getTroopSOAPImplPort();
        administratorSoap = new AdministratorSOAP_Service().getAdministratorSOAPImplPort();
        while (true) {
            System.out.println("Press \"1\" for Administrator");
            System.out.println("Press \"2\" for Troop");
            System.out.println("Press \"3\" to exit");
            input = new Scanner(System.in).nextLine();
            if (input.matches("1")) {
                adminMenu();
            } else if (input.matches("2")) {
                troopMenu();
            } else if (input.matches("3")) {
                System.out.println("CIAO!!");
                return;
            } else {
                System.out.println("Unknown entry");
            }
        }
    }

    private static void createAdmin() {
        String input;
        AdministratorDTO dto = new AdministratorDTO();
        System.out.println("Enter name:");
        dto.setName(getInput());
        System.out.println("Enter desc:");
        dto.setDescription(getInput());
        try {
            if (!isServerOnline()) {
                return;
            }
            System.out.println(adminToString(dto));
            administratorSoap.createAdministrator(dto);
            System.out.println("Successfully created new admin!");
        } catch (WebServiceException e) {
            System.out.println("Server unavailable.");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

    }

    public static AdministratorDTO retrieveAdmin() {
        String input;
        AdministratorDTO dto = null;
        System.out.println("Enter ID:");
        Long id;
        try {
            if (!serverAvailable("http://localhost:9000/DundD/soap/administrator?wsdl") || !serverAvailable("http://localhost:9000/DundD/soap/troop?wsdl")) {
                System.err.println("\n\n\n Server is not available. \n\n");
                return null;
            }
            id = Long.parseLong(getInput());
            dto = administratorSoap.retrieveAdministratorById(id);
            System.out.println(adminToString(dto));
        } catch (NumberFormatException e) {
            System.out.println("wrong number format");
        } catch (SOAPFaultException e) {
            System.out.println("Unable to retrieve admin with this ID");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

        return dto;
    }

    private static void updateAdmin() {
        String input;
        AdministratorDTO dto = retrieveAdmin();
        if (dto == null) {
            return;
        }
        System.out.println("Press \"1\" to update name");
        System.out.println("Press \"2\" to update description");

        input = new Scanner(System.in).nextLine();
        if (input.matches("1")) {
            System.out.println("Enter new name:");
            dto.setName(getInput());
        } else if (input.matches("2")) {
            System.out.println("Enter new description:");
            dto.setDescription(getInput());
        }

        try {
            if (isServerOnline()) {
                return;
            }
            System.out.println(adminToString(dto));
            administratorSoap.updateAdministrator(dto);
            System.out.println("Successfully updated admin!");
        } catch (SOAPFaultException e) {
            System.out.println("Error while retrieving admin");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

    }

    private static void deleteAdmin() {
        AdministratorDTO dto = retrieveAdmin();
        try {
            if (!isServerOnline()) {
                return;
            }
            administratorSoap.deleteAdministrator(dto);
            System.out.println("Deleted admin \"" + dto.getName() + "\"");
        } catch (SOAPFaultException e) {
            System.out.println("Error while deleting admin");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }
    }

    private static void retrieveAllAdmins() {
        List<AdministratorDTO> admins = null;
        try {
            if (!isServerOnline()) {
                return;
            }
            admins = administratorSoap.retrieveAllAdministrators();
        } catch (SOAPFaultException e) {
            System.out.println("Error while retrieving admins");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

        if ((admins == null) || admins.isEmpty()) {
            System.out.println("No administrators are present in the database");
        } else {
            System.out.println("All admins: ");
            for (AdministratorDTO administratorDTO : admins) {
                System.out.println(adminToString(administratorDTO));
            }
        }
    }

    public static boolean serverAvailable(String URLName) {
        try {
            HttpURLConnection.setFollowRedirects(false);
            HttpURLConnection connection =
                    (HttpURLConnection) new URL(URLName).openConnection();
            return (connection.getResponseCode() == HttpURLConnection.HTTP_OK);
        } catch (Exception e) {
            return false;
        }
    }

    private static String adminToString(AdministratorDTO a) {
        if (a == null) {
            return "";
        }
        String admin = "";
        if (a.getId() != null) {
            admin = "ID: " + a.getId().toString() + ", ";
        }
        admin = admin + "Name: " + a.getName() + ", Descr: " + a.getDescription();
        return admin;
    }

    private static void createTroop() {
        TroopDTO dto = new TroopDTO();
        System.out.println("Enter name:");
        dto.setName(getInput());
        System.out.println("Enter mission:");
        dto.setMission(getInput());
        System.out.println("Enter gold:");
        try {
            if (!isServerOnline()) {
                return;
            }
            dto.setGold(Integer.valueOf(getInput()));
            System.out.println(troopToString(dto));
            troopSoap.createTroop(dto);
            System.out.println("Successfully created!");
        } catch (NumberFormatException e) {
            System.out.println("wrong number format");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

    }

    public static TroopDTO retrieveTroop() {
        TroopDTO dto = null;
        System.out.println("Enter ID:");
        try {
            if (!isServerOnline()) {
                return null;
            }
            dto = troopSoap.retrieveTroopById(Long.parseLong(getInput()));
            System.out.println(troopToString(dto));
        } catch (NumberFormatException e) {
            System.out.println("wrong number format");
        } catch (SOAPFaultException e) {
            System.out.println("Unable to retrieve troop with this ID");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

        return dto;
    }

    private static void updateTroop() {
        String input;
        TroopDTO dto = retrieveTroop();
        if (dto == null) {
            return;
        }
        System.out.println("Press \"1\" to update name");
        System.out.println("Press \"2\" to update mission");
        System.out.println("Press \"3\" to update gold");
        input = new Scanner(System.in).nextLine();
        if (input.matches("1")) {
            System.out.println("Enter new name:");
            dto.setName(getInput());
        } else if (input.matches("2")) {
            System.out.println("Enter new mission:");
            dto.setMission(getInput());
        } else if (input.matches("3")) {
            System.out.println("Enter new gold:");
            try {
                dto.setGold(Integer.valueOf(getInput()));
            } catch (NumberFormatException e) {
                System.out.println("wrong number format");
            }
        }

        try {
            if (!isServerOnline()) {
                return;
            }
            System.out.println(troopToString(dto));
            troopSoap.updateTroop(dto);
            System.out.println("Successfully updated!");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

    }

    private static void deleteTroop() {
        TroopDTO dto = retrieveTroop();
        try {
            if (!isServerOnline()) {
                return;
            }
            troopSoap.deleteTroop(dto);
            System.out.println("Deleted troop \"" + dto.getName() + "\"");
        } catch (SOAPFaultException e) {
            System.out.println("Error while deleting");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }
    }

    private static void retrieveAllTroops() {
        List<TroopDTO> troops = null;
        try {
            if (!isServerOnline()) {
                return;
            }
            troops = troopSoap.retrieveAllTroops();
        } catch (SOAPFaultException e) {
            System.out.println("Error while retrieving troops");
        } catch (Exception e) {
            System.out.println("Unexpected error occured.");
        }

        if ((troops == null) || troops.isEmpty()) {
            System.out.println("No troops present in the database");
        } else {
            System.out.println("All troops: ");
            for (TroopDTO troop : troops) {
                System.out.println(troopToString(troop));
            }
        }
    }

    private static String troopToString(TroopDTO t) {
        if (t == null) {
            return "";
        }
        String admin = "";
        if (t.getId() != null) {
            admin = "ID: " + t.getId().toString() + ", ";
        }
        admin = admin + "Name: " + t.getName() + ", Mission: " + t.getMission() + ", Gold:" + t.getGold();
        return admin;
    }

    private static boolean isServerOnline() {
        if (!serverAvailable("http://localhost:9000/DundD/soap/administrator?wsdl") || !serverAvailable("http://localhost:9000/DundD/soap/troop?wsdl")) {
            System.err.println("\n\n Server is not available. \n\n");
            return false;
        }
        return true;
    }

    private static String getInput() {
        String input = null;
        int i = 0;
        while (input == null || input.trim().isEmpty()) {
            if (i > 0) {
                System.out.println("Input cannot be empty");
            }
            i++;
            input = new Scanner(System.in).nextLine();
        }
        return input;
    }

    private static void adminMenu() {
        String input;
        while (true) {
            System.out.println("Press \"1\" to create Administrator");
            System.out.println("Press \"2\" to retrieve Administrator");
            System.out.println("Press \"3\" to update Administrator");
            System.out.println("Press \"4\" to delete Administrator");
            System.out.println("Press \"5\" to list all Administrators");
            System.out.println("Press \"6\" to return to main menu");
            input = new Scanner(System.in).nextLine();
            if (input.matches("1")) {
                createAdmin();
            } else if (input.matches("2")) {
                retrieveAdmin();
            } else if (input.matches("3")) {
                updateAdmin();
            } else if (input.matches("4")) {
                deleteAdmin();
            } else if (input.matches("5")) {
                retrieveAllAdmins();
            } else if (input.matches("6")) {
                return;
            } else {
                System.out.println("Unknown entry");
            }
        }
    }

    private static void troopMenu() {
        String input;
        while (true) {
            System.out.println("Press \"1\" to create Troop");
            System.out.println("Press \"2\" to retrieve Troop");
            System.out.println("Press \"3\" to update Troop");
            System.out.println("Press \"4\" to delete Troop");
            System.out.println("Press \"5\" to list all Troops");
            System.out.println("Press \"6\" to return to main menu");
            input = new Scanner(System.in).nextLine();
            if (input.matches("1")) {
                createTroop();
            } else if (input.matches("2")) {
                retrieveTroop();
            } else if (input.matches("3")) {
                updateTroop();
            } else if (input.matches("4")) {
                deleteTroop();
            } else if (input.matches("5")) {
                retrieveAllTroops();
            } else if (input.matches("6")) {
                return;
            } else {
                System.out.println("Unknown entry");
            }
        }
    }
}